//
//  CharatersticStatistics.swift
//  home
//
//  Created by Yun Zeng on 2019/9/25.
//  Copyright © 2019 Yun Zeng. All rights reserved.
//

import Foundation

// MARK: - 时间转换
extension Date {
    func toString() -> String {
        let formatter = DateFormatter()
        formatter.locale = Locale.current
        formatter.dateFormat = "YYYY-MM-dd HH:mm:ss"
        return formatter.string(from: self)
    }
    
    func toString(format: String) -> String {
        let formatter = DateFormatter()
        formatter.locale = Locale.current
        formatter.dateFormat = format
        return formatter.string(from: self)
    }
    
}

extension String {
    func toDate() -> Date {
        let formatter = DateFormatter()
        formatter.dateFormat = "YYYY-MM-dd HH:mm:ss"
        return formatter.date(from: self)!
    }
}

// MARK: - 温度数据
let msgTemperatureData = """
{"after":"2019-09-23 21:22:25","aid":"00158d0002379233","before":"2019-09-24 21:22:25","cid":1,"logs":[{"time":"2019-09-23 22:35:23","value":24.01},{"time":"2019-09-24 00:01:49","value":23.8},{"time":"2019-09-24 03:43:41","value":24.31},{"time":"2019-09-24 04:02:12","value":24.81},{"time":"2019-09-24 04:29:25","value":25.32},{"time":"2019-09-24 05:14:49","value":25.85},{"time":"2019-09-24 06:26:20","value":26.37},{"time":"2019-09-24 07:38:21","value":26.89},{"time":"2019-09-24 08:41:35","value":27.43},{"time":"2019-09-24 09:31:50","value":27.37},{"time":"2019-09-24 09:36:46","value":26.94},{"time":"2019-09-24 09:41:58","value":26.42},{"time":"2019-09-24 09:48:25","value":25.91},{"time":"2019-09-24 10:03:09","value":25.4},{"time":"2019-09-24 10:17:54","value":24.88},{"time":"2019-09-24 11:40:04","value":25.39},{"time":"2019-09-24 11:52:43","value":25.92},{"time":"2019-09-24 12:16:50","value":26.46},{"time":"2019-09-24 12:46:04","value":27.34},{"time":"2019-09-24 12:46:09","value":27.41},{"time":"2019-09-24 12:46:14","value":27.56},{"time":"2019-09-24 12:46:20","value":27.65},{"time":"2019-09-24 12:46:40","value":27.74},{"time":"2019-09-24 14:38:07","value":28.24},{"time":"2019-09-24 15:52:54","value":29.2},{"time":"2019-09-24 15:52:59","value":29.58},{"time":"2019-09-24 15:53:14","value":29},{"time":"2019-09-24 15:53:24","value":29.1},{"time":"2019-09-24 15:53:30","value":29.32},{"time":"2019-09-24 15:53:35","value":29.44},{"time":"2019-09-24 15:53:50","value":29.62},{"time":"2019-09-24 15:58:42","value":29.09},{"time":"2019-09-24 16:07:00","value":29.47},{"time":"2019-09-24 16:07:10","value":30.24},{"time":"2019-09-24 16:07:20","value":30.85},{"time":"2019-09-24 16:07:25","value":31.05},{"time":"2019-09-24 16:07:31","value":31.12},{"time":"2019-09-24 16:07:41","value":31.21},{"time":"2019-09-24 16:09:07","value":30.68},{"time":"2019-09-24 16:10:08","value":30.1},{"time":"2019-09-24 16:11:38","value":29.57},{"time":"2019-09-24 16:14:14","value":29.05},{"time":"2019-09-24 16:18:56","value":28.54},{"time":"2019-09-24 16:41:42","value":28.02},{"time":"2019-09-24 16:43:18","value":27.48},{"time":"2019-09-24 16:45:14","value":26.98},{"time":"2019-09-24 16:47:40","value":26.42},{"time":"2019-09-24 16:51:11","value":25.91},{"time":"2019-09-24 17:04:01","value":25.4},{"time":"2019-09-24 17:23:46","value":25.5},{"time":"2019-09-24 17:54:00","value":25.23},{"time":"2019-09-24 18:11:01","value":25.34},{"time":"2019-09-24 18:22:04","value":25.87},{"time":"2019-09-24 18:41:10","value":26.37},{"time":"2019-09-24 19:11:04","value":26.89},{"time":"2019-09-24 19:27:14","value":26.58},{"time":"2019-09-24 19:45:55","value":26.34},{"time":"2019-09-24 20:30:02","value":26.2},{"time":"2019-09-24 20:36:55","value":26.13}],"sid":1}
""".data(using: .utf8)!

struct CharactersiticRecords: Codable {
    var aid: String
    var sid: Int
    var cid: Int
    var before: String
    var after: String
    struct Record: Codable {
        var time: String
        var value: AnyJSONType
    }
    var logs: [Record]
}

let message = try! JSONDecoder().decode(CharactersiticRecords.self, from: msgTemperatureData)


print("after: \(message.after) before: \(message.before)")

var logs = message.logs

// 数组为空
if logs.isEmpty {
    exit(0)
}

// 其实时间是否有值
if logs.first!.time != message.after {
    logs.insert(CharactersiticRecords.Record(time: message.after, value: logs.first!.value), at: 0)
}

// 结束时间是否有值
if logs.last!.time != message.before {
    logs.append(CharactersiticRecords.Record(time: message.before, value: logs.last!.value))
}


for (i, v) in  logs.enumerated() {
    print("[\(String(format: "%02d", i))] \(v.time)  \(String(format: "%0.1f", v.value.toValueFloat()!))")
}

let timeStart = message.after.toDate()

var maxLog, minLog: CharactersiticRecords.Record
maxLog =  logs.first!
minLog = logs.first!
var average: Float = 0

for i in 1..<logs.count {
    if logs[i].value.toValueFloat()! > maxLog.value.toValueFloat()! {
        maxLog = logs[i]
    } else if logs[i].value.toValueFloat()! < minLog.value.toValueFloat()! {
        minLog = logs[i]
    }
    let interval = logs[i].time.toDate().timeIntervalSince(logs[i-1].time.toDate())
    average += Float(interval) * (logs[i].value.toValueFloat()! + logs[i-1].value.toValueFloat()!) / 2
}
let interval = logs.last!.time.toDate().timeIntervalSince(logs.first!.time.toDate())
average = average / Float(interval)

print("average: \(String(format: "%0.1f", average))")
print("max: \(String(format: "%0.1f", maxLog.value.toValueFloat()!)) at: \(maxLog.time)")
print("min: \(String(format: "%0.1f", minLog.value.toValueFloat()!)) at: \(minLog.time)")

let max = maxLog.value.toValueFloat()!
let min = minLog.value.toValueFloat()!

let height = (max - average) > (average - min) ? (max - average) * 2.2 : (average - min) * 2.2
print("height: \(height) low: \(average - height / 2) high: \(average + height / 2)")

let xStart = average - height / 2

var entries = [CGPoint]()

for i in 1 ..< logs.count {
    let xp = logs[i].time.toDate().timeIntervalSince(timeStart) / interval
    let yp = (logs[i].value.toValueFloat()! - xStart) / height
    entries.append(CGPoint(x: xp, y: Double(yp)))
    print("x: \(String(format: "%0.2f", xp)) y: \(String(format: "%0.2f", yp))")
}

//
let now = Date()
print("now: \(now.toString(format: "HH:mm"))")


/**
 
 
 let configFile = Storage.Path.appendingPathComponent("account").appendingPathExtension("json")

 guard let data = try? Data(contentsOf: configFile), let membership = try? JSONDecoder().decode(Membership.self, from: data) else {
         exit(-1)
 }

 let home = "187c7894-1d3d-442b-9d3a-d2ebcfa86a6c"

 extension Date {
     func toString() -> String {
         let formatter = DateFormatter()
         formatter.locale = Locale.current
         formatter.dateFormat = "YYYY-MM-dd HH:mm:ss"
         return formatter.string(from: self)
     }
     
     func toString(format: String) -> String {
         let formatter = DateFormatter()
         formatter.locale = Locale.current
         formatter.dateFormat = format
         return formatter.string(from: self)
     }
 }

 extension String {
     func toDate() -> Date {
         let formatter = DateFormatter()
         formatter.dateFormat = "YYYY-MM-dd HH:mm:ss"
         return formatter.date(from: self)!
     }
 }

 let before = Date()
 let after = before.advanced(by: -TimeInterval(24 * 60 * 60 * 7))
 let aid = "00158d000215112f"
 let sid = 1
 let cid = 1

 print("before: \(before.toString())")
 print("after: \(after.toString())")

 struct CharateristicQueryInfo: Codable {
     var aid: String
     var sid: Int
     var cid: Int
     var before: String?
     var after: String?
     var limit: Int?
 }

 let info = CharateristicQueryInfo(aid: aid, sid: sid, cid: cid, before: nil, after: nil, limit: 10)
 let msg = CloudMessage(path: "home/characteristic/log", method: .get, object: info)
 msg.home = home

 print("message: \(msg.description)")

 var rspMsg: CloudMessage?
 let semaphore = DispatchSemaphore(value: 0)
 _ = HttpClient.post(membership: membership, home: home, message: msg, completionHandler: { (result) in
     rspMsg = result
     semaphore.signal()
 })

 semaphore.wait()

 guard let result = rspMsg, let data = result.data else {
     exit(-1)
 }

 struct CharactersiticLogs: Codable {
     var aid: String
     var sid: Int
     var cid: Int
     var before: String?
     var after: String?
     var limits: Int?
     struct CharacteristicLog: Codable {
         var time: String
         var value: AnyJSONType
     }
     var logs: [CharacteristicLog]
 }


 extension CharactersiticLogs: CustomStringConvertible {
     var description: String {
         let data = try! JSONEncoder().encode(self)
         return String(bytes: data, encoding: .utf8)!
     }
 }


 let pkg = try JSONDecoder().decode(CharactersiticLogs.self, from: result.data!)
 print("pkg: \(pkg)")

 let now = Date()

 class LogClassification {
     var daysAgo: Int
     var dayDesc: String
     struct Record {
         var time: String
         var desc: String
     }
     var records = [Record]()
     
     init(daysAgo: Int, dayDesc: String) {
         self.daysAgo = daysAgo
         self.dayDesc = dayDesc
     }
 }

 var logs = [LogClassification]()

 for v in pkg.logs {
     let date = v.time.toDate()
     let components = Calendar.current.dateComponents(in: .current, from: date)
     let daysAgo = Int(now.timeIntervalSince1970 / (24 * 60 * 60)) - Int(date.timeIntervalSince1970 / (24 * 60 * 60))

     var dateDesc = ""
     switch daysAgo {
     case 0:
         dateDesc += "今天"
     case 1:
         dateDesc += "昨天"
     case 2:
         dateDesc += "前天"
     case 2...:
         dateDesc += String(format: "%d天前", daysAgo)
     default:
         break
     }
     let weeks = ["日", "一", "二",  "三",  "四",  "五",  "六"]
     dateDesc += (" 星期" + weeks[components.weekday! - 1])

     var timeDesc = ""
     switch (components.hour!) {
     case 0 ..< 6:
         timeDesc += "凌晨 " + String(format: "%d:%02d", components.hour!, components.minute!)
     case 6 ..< 12:
         timeDesc += "上午 " + String(format: "%d:%02d", components.hour!, components.minute!)
     case 12:
         timeDesc += "中午 " + String(format: "%d:%02d", components.hour!, components.minute!)
     case 13 ..< 18:
         timeDesc += "下午 " + String(format: "%d:%02d", components.hour! - 12, components.minute!)
     case 18 ..< 24:
         timeDesc += "傍晚 " + String(format: "%d:%02d", components.hour! - 12, components.minute!)
     default:
         break
     }
     
     var valueDesc = ""
     if v.value.toValueInt() == 0 {
         valueDesc = "窗户关了"
     } else {
         valueDesc = "窗户开了"
     }
     
     if  let last = logs.last, last.daysAgo == daysAgo {
         last.records.append(LogClassification.Record(time: timeDesc, desc: valueDesc))
     } else {
         let log = LogClassification(daysAgo: daysAgo, dayDesc: dateDesc)
         log.records.append(LogClassification.Record(time: timeDesc, desc: valueDesc))
         logs.append(log)
     }
     print("\(v.time) \(dateDesc) \(timeDesc) \(valueDesc)")
 }

 print("\n")

 for log in logs {
     print("\(log.dayDesc)")
     for record in log.records {
         print("\t \(record.time)\t\(record.desc)")
     }
 }


 
 
 */
